#include"zookeeperuti.h"
#include"mprpc.h"
#include<iostream>
#include<semaphore.h>

void global_watcher(zhandle_t* zh,int type,int state,const char* path,void* watchctx)
{
    if(type==ZOO_SESSION_EVENT)     //回调的消息类型
    {   
        if(state==ZOO_CONNECTED_STATE)
        {
            sem_t* sem=(sem_t*)zoo_get_context(zh);     //通知主线程
            sem_post(sem);
        }

    }
}


ZkClient::ZkClient()
    :_zhandle(nullptr)
{}

ZkClient::~ZkClient()
{
    if(_zhandle!=nullptr)
    {
        zookeeper_close(_zhandle);  //释放资源
    }
}

//连接zkserver
void ZkClient::Start()
{   
    std::string host=Mprpc::GetConfig().GetItem("zookeeperip");
    std::string port=Mprpc::GetConfig().GetItem("zookeeperport");
    std::string connstr=host+":"+port;
    
    //三线程 api调用线程 网络IO线程(epoll) watcher回调线程
    _zhandle=zookeeper_init(connstr.c_str(),global_watcher,30000,nullptr,nullptr,0);
    if(_zhandle==nullptr)
    {
        std::cout << "zookeeper init error!" << std::endl;
        exit(EXIT_FAILURE);
    }

    sem_t sem;
    sem_init(&sem,0,0);

    zoo_set_context(_zhandle,&sem);
    sem_wait(&sem);
    
    std::cout << "zookeeper init success!" << std::endl;
}

//创建znode节点
void ZkClient::Create(const char* path,const char* data,int datalen,int state)
{
    char path_buf[128];
    int bufferlen=sizeof(path_buf);
    int flag;
    //判断节点是否存在
    flag=zoo_exists(_zhandle,path,0,nullptr);
    if(ZNONODE==flag)   //path的node节点不存在
    {
        //创建节点
        flag==zoo_create(_zhandle,path,data,datalen,&ZOO_OPEN_ACL_UNSAFE,state,path_buf,bufferlen);
        if(flag==ZOK)
        {
            std::cout << "znode create success path:" << path << std::endl;
        }
        else
        {
            std::cout << "znode create success path:" << path << std::endl;
            return;
        }
    }
}

//获取path节点数据
std::string ZkClient::GetData(const char* path)
{
    char buffer[64];
    int buflen=sizeof(buffer);
    int flag=zoo_get(_zhandle,path,0,buffer,&buflen,nullptr);
    if(flag!=ZOK)
    {
        std::cout << "get znode err path:" << path << std::endl;
        return "";
    }
    else
    {
        return buffer;
    }
}